package cn.fscode.code.generator.service.impl;

import cn.fscode.code.generator.gen.GeneratorConfig;
import cn.fscode.code.generator.gen.SQLService;
import cn.fscode.code.generator.gen.SQLServiceFactory;
import cn.fscode.code.generator.gen.TableDefinition;
import cn.fscode.code.generator.model.po.DatasourceConfigPO;
import cn.fscode.code.generator.model.po.GenTablePO;
import cn.fscode.code.generator.model.req.DatasourceConfigQueryReq;
import cn.fscode.code.generator.model.req.DbTableReq;
import cn.fscode.code.generator.model.resp.DatasourceResp;
import cn.fscode.code.generator.repository.DatasourceConfigRepository;
import cn.fscode.code.generator.repository.GenTableColumnRepository;
import cn.fscode.code.generator.repository.GenTableIndexRepository;
import cn.fscode.code.generator.repository.GenTableRepository;
import cn.fscode.code.generator.service.DatasourceConfigService;
import cn.fscode.commons.tool.core.StringUtils;
import cn.fscode.commons.tool.core.exception.BizException;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author shenguangyang
 */
@Service
@RequiredArgsConstructor
public class DatasourceConfigServiceImpl implements DatasourceConfigService {
    private final DatasourceConfigRepository datasourceConfigRepository;
    private final GenTableIndexRepository genTableIndexRepository;
    private final GenTableColumnRepository genTableColumnRepository;
    private final GenTableRepository genTableRepository;

    @Override
    public DatasourceConfigPO getById(Long id) {
        return datasourceConfigRepository.getById(id);
    }

    @Override
    public List<DatasourceResp> listAll() {
        return datasourceConfigRepository.listAllDatasourceResp();
    }

    @Override
    public void save(DatasourceConfigPO datasourceConfigPO) {
        if (!datasourceConfigRepository.save(datasourceConfigPO)) {
            throw new BizException("保存失败");
        }
    }

    @Override
    public void update(DatasourceConfigPO datasourceConfigPO) {
        if (!datasourceConfigRepository.updateById(datasourceConfigPO)) {
            throw new BizException("更新失败");
        }
    }

    @Override
    @Transactional
    public void delete(DatasourceConfigPO datasourceConfigPO) {
        List<GenTablePO> genTableList = genTableRepository.listByDatasourceId(datasourceConfigPO.getId());
        if (!genTableList.isEmpty()) {
            List<Long> tableIds = genTableList.stream().map(GenTablePO::getId).collect(Collectors.toList());
            genTableRepository.removeByIds(tableIds);
            genTableIndexRepository.deleteBatchByTableIds(tableIds);
            genTableColumnRepository.deleteBatchByTableIds(tableIds);
        }
        if (!datasourceConfigRepository.removeById(datasourceConfigPO)) {
            throw new BizException("删除失败");
        }
    }

    @Override
    public IPage<DatasourceConfigPO> page(DatasourceConfigQueryReq req) {
        return datasourceConfigRepository.pageDataSourceConfig(req);
    }

    @Override
    public List<TableDefinition> listTable(DbTableReq req) {
        DatasourceConfigPO dataSourceConfigPO = datasourceConfigRepository.getById(req.getDatasourceId());
        GeneratorConfig generatorConfig = GeneratorConfig.build(dataSourceConfigPO);
        SQLService service = SQLServiceFactory.build(generatorConfig);
        // 筛选表
        if (StringUtils.isNotEmpty(req.getTableName())) {
            Pattern pattern = Pattern.compile(".*" + req.getTableName() + ".*");
            return service.getTableSelector(generatorConfig).getSimpleTableDefinitions()
                    .stream().filter(x -> pattern.matcher(x.getTableName()).matches()).collect(Collectors.toList());
        } else {
            return service.getTableSelector(generatorConfig).getSimpleTableDefinitions();
        }
    }

    @Override
    public void deleteBatchByIds(List<Long> ids) {
        datasourceConfigRepository.removeByIds(ids);
    }
}
